// Copyright 1998-2017 Epic Games, Inc. All Rights Reserved.

#pragma once

#include "WiiRemoteDeviceState.h"
#include "Runtime/InputDevice/Public/IInputDevice.h"
extern "C"
{
#include "wiiuse.h"
}

#define MAX_WIIMOTES        4

class FWiiRemoteDevice : public IInputDevice
{
public:
    FWiiRemoteDevice(const TSharedRef< FGenericApplicationMessageHandler >& InMessageHandler);

    virtual ~FWiiRemoteDevice();

    static void PreInit();

    static void LoadConfig();

    //IInputDevice overrides
    virtual void Tick(float DeltaTime) override;
    virtual void SendControllerEvents() override;
    virtual void SetMessageHandler(const TSharedRef< FGenericApplicationMessageHandler >& InMessageHandler) override;
    virtual bool Exec(UWorld* InWorld, const TCHAR* Cmd, FOutputDevice& Ar) override;
    virtual void SetChannelValue(int32 ControllerId, FForceFeedbackChannelType ChannelType, float Value) override;
    virtual void SetChannelValues(int32 ControllerId, const FForceFeedbackValues& Values) override;

    bool Connect();
    bool IsConnected() { return DeviceConnected > 0; }
    void Disconnect();
    void SetIREnabled(int32 ControllerId, bool IsEnabled);
    void SetMotionPlusEnabled(int32 ControllerId, bool IsEnabled);
    void SetMotionSensingEnabled(int32 ControllerId, bool IsEnabled);
    void SetRumbleEnabled(int32 ControllerId, bool IsEnabled);

private:
    struct FControllerState
    {
        bool ButtonStates[EWiiRemoteDeviceButton::WIIREMOTE_BTN_COUNT];

        double NextRepeatTime[EWiiRemoteDeviceButton::WIIREMOTE_BTN_COUNT];

        int32 ControllerId;

        struct wiimote_t* WiiMote;
    };

    bool AnyWiiRemoteConnected();

    void HandleEvent(struct wiimote_t* wm, int id);
    void HandleCtrlStatus(struct wiimote_t* wm, int id);
    void HandleDisconnect(struct wiimote_t* wm, int id);

private:
    TSharedPtr<FGenericApplicationMessageHandler> MessageHandler;

    FWiiRemoteDeviceKeyNames::Type Buttons[EWiiRemoteDeviceButton::WIIREMOTE_BTN_COUNT];
    bool CurrentStates[EWiiRemoteDeviceButton::WIIREMOTE_BTN_COUNT];

    FControllerState    ControllerStates[MAX_WIIMOTES];
    struct wiimote_t**  AllWiimotes;

    float InitialButtonRepeatDelay;
    float ButtonRepeatDelay;

    int DeviceFound;
    int DeviceConnected;
};

DEFINE_LOG_CATEGORY_STATIC(LogWiiRemoteDevice, Log, All);